#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct Link *AppendNode(struct Link *head,int data);//附加节点
void DisplayNode(struct Link *head);//打印节点
struct Link *DeleteMemory(struct Link *head);//删除节点

struct Link
{
	int data;			//定义数据域
	struct Link *_next; //定义指针域，存储直接后继的节点信息
} linklist;

int main(void)
{
	int i = 0;
	char rec[10];

	/* 建立一个单项链表 */
	struct Link *head = NULL; //创建头指针，初始化为NULL

	//如果确定继续添加结点
	while (1)
	{
		printf("请输入对应的指令执行操作:");
		scanf("%s", rec);

		if(strstr(rec,"add") != NULL)
		{
			//通过函数获得链表的地址，AppendNode函数返回的是链表的头指针,
			//可以根据头指针指向的地址来获取链表中保存的数据
			head = AppendNode(head,i);
			DisplayNode(head); //根据头指针打印链表
			i++;
		}
		else if (strstr(rec,"delete") != NULL)
		{
			printf("清空链表\r\n");
			head = DeleteMemory(head);
			i = 0;
		}
		else
		{
			printf("指令输入错误\r\n");
		}

		strcpy(rec,"");
	}

	return 0;
}

struct Link *AppendNode(struct Link *head,int data)
{
	struct Link *p = NULL, *pr = head; //创建p指针，初始化为null；创建pr指针，初始化为head

	//为指针p申请内存空间，必须操作，因为p是新创建的节点
	p = (struct Link *)malloc(sizeof(struct Link));

	//如果申请内存失败，则退出程序
	if (p == NULL)
	{
		printf("NO enough memory to allocate!\n");
		exit(0);
	}

	//若单链表为空表，则将新建节点置为头节点
	if (head == NULL)
	{
		head = p; //使head指针指向p的地址(p已经通过malloc申请了内存，所以有地址）
	}
	//链表非空，则将新建节点添加到表尾
	else
	{
		//此时链表已经有头节点 ，再一次执行了AppendNode函数
		//因为第一次添加头节点时，pr = head，和头指针一样指向头节点的地址
		while(pr->_next != NULL)//当pr指向的地址，即此时的p的指针域不为NULL(即p不是尾节点)
		{
			pr = pr->_next;//使pr指向头节点的指针域
		}
		pr->_next = p;//使pr的指针域指向新键节点的地址，此时的next指针域是头节点的指针域
	}

	// printf("Input node data:");
	// scanf("%d", &data);
	p->data = data;
	p->_next = NULL; //新添加的节点位于表尾，所以它的指针域为NULL

	return head; //返回head的地址
}

//输出函数，打印链表
void DisplayNode(struct Link *head)
{
	struct Link *p = head; //定义p指针使其指向头节点
	int j = 1;			   //定义j记录这是第几个数值

	//因为p = p->next,所以直到尾节点打印结束
	while (p != NULL)
	{
		printf("%5d%10d\n", j, p->data);

		//因为节点已经创建成功，所以p的指向由头节点指向下一个节点(每一个节点的指针域都指向了下一个节点)
		p = p->_next;
		j++;
	}
}

//删除节点,释放资源函数
struct Link *DeleteMemory(struct Link *head)
{
	struct Link *p = head, *pr = NULL; //定义p指针指向头结点
	while(p != NULL)//当p的指针域不为NULL
	{
		pr = p;//将每一个结点的地址赋值给pr指针
		p = p->_next;
		// pr->_next = NULL;
		free(pr);
	}

	head = NULL;
	return head;
}
